package org.lora.core.mongodb.impl;

import java.util.ArrayList;
import java.util.List;

import org.bson.Document;
import org.bson.conversions.Bson;
import org.lora.core.mongodb.IMongoDAO;
import org.lora.core.mongodb.MongoParamEntity;
import org.lora.exception.LoraCoreException;
import org.lora.exception.MongoDBException;
import org.lora.exception.ParameterIllegalException;
import org.lora.util.StringUtil;
import org.lora.util.ValidateUtil;

import com.mongodb.MongoClient;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.model.Filters;
import com.mongodb.client.model.Updates;
import com.mongodb.client.result.DeleteResult;
import com.mongodb.client.result.UpdateResult;

/**
 * <p>
 * Title:MongoDAOImpl
 * </p>
 * <p>
 * Desription:连接MongoDB数据库的DAO实现
 * </p>
 * Create Time:2016年7月7日 下午2:41:30
 * 
 * @author Bladnir@outlook.com
 *         <p>
 *         History:
 *         </p>
 *         2016年7月7日 Bladnir Create</br>
 */
public class MongoDAOImpl implements IMongoDAO {

	/**
	 * The MongoClient instance actually represents a pool of connections to the
	 * database<br>
	 * you will only need one instance of class MongoClient even with multiple
	 * threads<br>
	 */
	private MongoClient mongoClient = null;

	/**
	 * 构造方法
	 * 
	 * @param mongoClient
	 */
	public MongoDAOImpl(MongoClient mongoClient) {
		this.mongoClient = mongoClient;
	}

	/**
	 * 根据数据库名和collectionName获取MongoCollection
	 * 
	 * @param dbName
	 * @param collectionName
	 * @return
	 * @throws MongoDBException
	 * @throws ParameterIllegalException 
	 */
	@Override
	public MongoCollection<Document> getMongoCollection(String dbName, String collectionName) throws LoraCoreException {

		ValidateUtil.isNull(dbName, "dbName");
		ValidateUtil.isNull(collectionName, "collectionName");
		ValidateUtil.isNull(mongoClient, "mongoClient");

		// 获取指定的数据库
		MongoDatabase database = mongoClient.getDatabase(dbName);

		if (database == null) {
			throw new MongoDBException("cant find MongoDatabase by dbName[" + dbName + "]");
		}

		// 获取指定的MongoCollection集合
		MongoCollection<Document> mongoCollection = database.getCollection(collectionName);

		if (mongoCollection == null) {
			throw new MongoDBException("cant find MongoCollection by collectionName[" + collectionName + "]");
		} else {
			return mongoCollection;
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.lora.core.mongodb.IMongoDAO#insert(java.lang.String,
	 * java.lang.String, java.util.List)
	 */
	@Override
	public void insert(String dbName, String collectionName, List<Document> documentList) throws LoraCoreException {

		if (ValidateUtil.isEmpty(documentList)) {
			return;
		}

		// 获取MongoCollection
		MongoCollection<Document> mongoCollection = getMongoCollection(dbName, collectionName);

		// 插入
		mongoCollection.insertMany(documentList);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.lora.core.mongodb.IMongoDAO#delete(java.lang.String,
	 * java.lang.String, java.lang.String, java.lang.String)
	 */
	@Override
	public DeleteResult delete(String dbName, String collectionName, String key, String value) throws LoraCoreException {

		if (StringUtil.isNull(key) || StringUtil.isNull(value)) {
			throw new MongoDBException("parameter illegal key=[" + key + "] value=[" + value + "]");
		}
		// 获取MongoCollection
		MongoCollection<Document> mongoCollection = getMongoCollection(dbName, collectionName);

		// 执行删除操作
		return mongoCollection.deleteMany(Filters.eq(key, value));
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.lora.core.mongodb.IMongoDAO#delete(java.lang.String,
	 * java.lang.String, org.bson.conversions.Bson)
	 */
	@Override
	public DeleteResult delete(String dbName, String collectionName, Bson bson) throws LoraCoreException {
		// 获取MongoCollection
		MongoCollection<Document> mongoCollection = getMongoCollection(dbName, collectionName);

		// 执行删除操作
		return mongoCollection.deleteMany(bson);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.lora.core.mongodb.IMongoDAO#update(java.lang.String,
	 * java.lang.String, org.lora.core.mongodb.MongoParamEntity,
	 * org.lora.core.mongodb.MongoParamEntity)
	 */
	@Override
	public UpdateResult update(String dbName, String collectionName, MongoParamEntity paramEntity, MongoParamEntity updateEntity)
			throws LoraCoreException {

		// 获取MongoCollection
		MongoCollection<Document> mongoCollection = getMongoCollection(dbName, collectionName);

		// 查询条件
		Bson paramBson = Filters.eq(paramEntity.getFieldName(), paramEntity.getFieldValue());

		// 实际进行更新的内容
		Bson updateBson = Updates.set(updateEntity.getFieldName(), updateEntity.getFieldValue());

		// 更新操作
		return mongoCollection.updateMany(paramBson, updateBson);

	}

	@Override
	public UpdateResult update(String dbName, String collectionName, Bson paramBson, Bson updateBson) throws LoraCoreException {

		if (paramBson == null || updateBson == null) {
			return null;
		}

		// 获取MongoCollection
		MongoCollection<Document> mongoCollection = getMongoCollection(dbName, collectionName);

		// 更新操作
		return mongoCollection.updateMany(paramBson, updateBson);

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.lora.core.mongodb.IMongoDAO#find(java.lang.String,
	 * java.lang.String, java.lang.String, java.lang.String)
	 */
	@Override
	public List<Document> find(String dbName, String collectionName, String key, String value) throws LoraCoreException {

		if (StringUtil.isNull(key) || StringUtil.isNull(value)) {
			throw new MongoDBException("parameter illegal key=[" + key + "] value=[" + value + "]");
		}

		// 获取MongoCollection
		MongoCollection<Document> mongoCollection = getMongoCollection(dbName, collectionName);
		// 查询结果集

		return mongoCollection.find(Filters.eq(key, value)).into(new ArrayList<Document>());

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.lora.core.mongodb.IMongoDAO#find(java.lang.String,
	 * java.lang.String, org.bson.conversions.Bson)
	 */
	@Override
	public List<Document> find(String dbName, String collectionName, Bson bson) throws LoraCoreException {

		// 获取MongoCollection
		MongoCollection<Document> mongoCollection = getMongoCollection(dbName, collectionName);
		// 查询结果集
		return mongoCollection.find(bson).into(new ArrayList<Document>());

	}

}
